﻿/* PCi AvP Bench Tool - Benchmark automation for AvP 2010 DX11 Demo
   Copyright © 2011, LEGRAND David
   Mail : david@pcinpact.com

   http://code.google.com/p/pci-gbs/

   This file is part of PCi AvP Bench Tool.

   PCi AvP Bench Tool is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   PCi AvP Bench Tool is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with PCi AvP Bench Tool.  If not, see <http://www.gnu.org/licenses/>.
 
   You're not allowed to use PC INpact name or logo without permission */

using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using PCi_GBS_DLL;
using System.Threading.Tasks;

namespace PCi_AvP_Bench_Tool
{
    public partial class main_form : Form
    {
        // On définit les paramètres par défaut du bench
        string exe = "AvP_D3D11_Benchmark.exe";
        string folder = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) + "\\Rebellion\\AvP D3D11 Benchmark\\";
        string ini_file = "avp_config.ini";
        string saved = "avp_queue.txt";
        string log = "avp_log.txt";

        // On récupère la résolution de l'écran
        string w_sys = SystemInformation.PrimaryMonitorSize.ToString().Split(',')[0].Split('=')[1];
        string h_sys = SystemInformation.PrimaryMonitorSize.ToString().Split(',')[1].Split('=')[1].Split('}')[0];

        // On initialise les outils
        Tools_AvP t = new Tools_AvP();

        public main_form()
        {
            InitializeComponent();

            // On donne à la fenêtre le nom de l'application 
            this.Text = Application.ProductName + " " + Application.ProductVersion;

            // On ne rajoute une résolution que si elle n'a pas déjà été ajoutée
            foreach (var result in t.Get_Resolutions())
            {
                if (!res_combo.Items.Contains(result["HorizontalResolution"] + "x" + result["VerticalResolution"])) res_combo.Items.Add(result["HorizontalResolution"] + "x" + result["VerticalResolution"]);
            }

            // On sélectionne les premières valeurs des ComboBox
            texture_combo.SelectedIndex = shadow_combo.SelectedIndex = aa_combo.SelectedIndex = af_combo.SelectedIndex = 0;

            // On sélectionne la résolution courante par défaut
            res_combo.SelectedIndex = res_combo.Items.IndexOf(w_sys + "x" + h_sys);

            // Si une queue sauvegardée existe, on active le bouton de load
            if (File.Exists(saved)) load_button.Enabled = true;

            Get_INI();
        }

        // La fonction qui gère le fichier de configuration
        private void Get_INI()
        {
        check_file:

            // Si le path par défaut de l'outil est valides, on affiche l'adresse du fichier dans la TextBox dédiée
            if (File.Exists(folder + exe))
            {
                path_show.Text = folder + exe;
            }

            // Sinon on vérifie l'existence d'un fichier de config
            else if (File.Exists(ini_file))
            {
                try
                {
                    string ini_path = File.ReadAllText(ini_file).Split('=')[1].Trim();
                    exe = t.Get_EXE(ini_path);
                    folder = t.Get_Folder(exe, ini_path);
                    goto check_file;
                }

                // En cas de problème avec le fichier de configuration, on le supprime et on repart à zéro
                catch
                {
                    MessageBox.Show("Config file is corrupted. It will be deleted.");
                    File.Delete(ini_file);
                    goto check_file;
                }
            }

            // Sinon, on ouvre une fenêtre permettant à l'utilisateur d'indiquer l'emplacement du fichier
            else
            {
                MessageBox.Show("Benchmark Exe file not found. Locate it.", "File not found", MessageBoxButtons.OK, MessageBoxIcon.Error);

                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    path_show.Text = openFileDialog1.FileName;

                    // Celui-ci est alors enregistré
                    File.WriteAllText(ini_file, "bench_path = " + openFileDialog1.FileName);
                    exe = t.Get_EXE(path_show.Text);
                    folder = t.Get_Folder(exe, path_show.Text);
                }
            }
        }

        // On lance le bench en fonction des paramètres indiqués
        private void Bench(string w, string h, int nb, string p)
        {
            // On initialise la variable de total qui sera utilisée pour le calcul de la moyenne
            decimal total = 0;

            // On créé le benchmark et on lui indique ses paramètres
            AvP_Bench b = new AvP_Bench();
            b.exe = exe;
            b.folder = folder;

            // On créé le fichier de config
            b.Write_Config(w, h, p);

            // On écrit une ligne indiquant le test en cours dans la textbox de sortie
            sortie_textbox.AppendText(w + "x" + h + " - " + t.param_to_human(p) + " :" + Environment.NewLine);

            // On lance le test autant de fois que demandé
            for (int i = 0; i < nb; i++)
            {
                decimal fps = b.Bench();

                // On incrémente le total
                total += fps;

                // On affiche le résultat
                sortie_textbox.Text += "   " + (i + 1) + ". " + fps + " FPS" + Environment.NewLine;
                t.Sortie_Bottom(sortie_textbox);
            }

            // Si l'on a demandé plus d'un test, on calcule la moyenne
            if (nb != 1) sortie_textbox.Text += "Average : " + Math.Round((total / nb), 2) + " FPS" + Environment.NewLine;

            // On va en bas de la textbox
            t.Sortie_Bottom(sortie_textbox);
        }

        // On récupère l'état des contrôle et l'on créé une ligne de paramètres "humaine"
        private string get_controls()
        {
            string s = "";

            // Si l'on a demandé un test CPU on utilise une résolution de 800x600 et les paramètres mini
            if (cpu_check.Checked)
            {
                s = "800x600 - T0 / S0 / AF 1x / AA 1x - " + nb.Value + "x";
            }
            // Si ce n'est pas le mode CPU qui est utilisé, on récupère les paramètres du formulaire
            else
            {
                s = res_combo.Text.Split('x')[0] + "x" +
                    res_combo.Text.Split('x')[1] + " -" +
                    " T" + texture_combo.Text.Substring(0, 1) + " /" +
                    " S" + shadow_combo.Text.Substring(0, 1) + " /" +
                    " AF " + af_combo.Text.Replace("x", "") + "x /" +
                    " AA " + aa_combo.Text.Replace("x", "") + "x";

                if (ssao_check.Checked) s += " / SSAO";
                if (tess_check.Checked) s += " / Tessellation";
                if (ass_check.Checked) s += " / Adv. shadow sampling";

                s += " - " + nb.Value.ToString() + "x";

            }

            return s;
        }

        // Lorsque l'on demande le lancement des tests
        private void go_button_Click(object sender, EventArgs e)
        {

            // On vide le champ de sortie
            sortie_textbox.Text = string.Empty;

            // On utilise la récupération d'erreur
            try
            {
                // Si il y a des données dans la queue
                if (queue_textbox.Lines.Length > 1)
                {
                    // On lit la queue
                    string[] lines = queue_textbox.Lines;

                    // Pour chaque lignes du tableau 
                    foreach (string l in lines)
                    {
                        // On créé un variable contenant les paramètres
                        string l_p = l;

                        // Si la ligne contient du texte 
                        if (l.Length > 2)
                        {
                            // Si la ligne n'est pas un commentaire
                            if (l.Substring(0, 2) != "//")
                            {
                                // On converti la ligne en paramètres
                                l_p = t.human_to_param(l);
                            }
                        }

                        // Si l'on compte bien 10 paramètres
                        if (l_p.Split(',').Length == 10)
                        {
                            // On traite les paramètre pour récupérer les informations utiles
                            string w = l_p.Split(',')[0];
                            string h = l_p.Split(',')[1];
                            int nb = int.Parse(l_p.Split(',')[2]);
                            string p = l_p.Split(',')[3] + l_p.Split(',')[4] + l_p.Split(',')[5] + l_p.Split(',')[6] + l_p.Split(',')[7] + l_p.Split(',')[8] + l_p.Split(',')[9];

                            // On lance le test
                            Bench(w, h, nb, p);
                        }
                    }
                }

                // Si la queue est vide, on passe en exécution "one-shot"
                else
                {
                    // En fonction de la case CPU Mode
                    if (cpu_check.Checked == false)
                    {
                        // On récupère les variables des contrôles 
                        string[] p = t.human_to_param(get_controls()).Split(',');

                        if (p.Length == 10)
                        {
                            // On lance le bench avec les paramètres récupérés
                            Bench(p[0], p[1], int.Parse(p[2]), p[3] + p[4] + p[5] + p[6] + p[7] + p[8] + p[9]);
                        }
                    }
                    else
                    {
                        // On lance le bench avec les paramètres CPU
                        Bench("800", "600", (int)nb.Value, "00010001");
                    }

                }

                // Dans tous les cas, on créé un fichier de log à la fin
                File.WriteAllText(log, sortie_textbox.Text);
            }

            //Si une erreur survient
            catch
            {
                t.Error_Box();
            }
        }

        // Lorsque l'URL est cliquée
        private void URL_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            // Si l'URL est cliquée, on ouvre PC INpact
            Process.Start("http://www.pcinpact.com");
        }

        // Lorsque la case CPU Mode est cochée
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            // Si l'option est cochée, on désactive toutes les options
            if (cpu_check.Checked)
            {
                texture_combo.Enabled = shadow_combo.Enabled = af_combo.Enabled = aa_combo.Enabled = ssao_check.Enabled = tess_check.Enabled = ass_check.Enabled = false;
            }
            // Sinon, on les active
            else
            {
                texture_combo.Enabled = shadow_combo.Enabled = af_combo.Enabled = aa_combo.Enabled = ssao_check.Enabled = tess_check.Enabled = ass_check.Enabled = true;
            }
        }

        // Lorsque l'on demande un reset des paramètres
        private void reset_button_Click(object sender, EventArgs e)
        {
            texture_combo.SelectedIndex = shadow_combo.SelectedIndex = aa_combo.SelectedIndex = af_combo.SelectedIndex = 0;
            ssao_check.Checked = tess_check.Checked = ass_check.Checked = cpu_check.Checked = false;
        }

        // Lorsque l'on demande un nettoyage de la queue
        private void clear_button_Click(object sender, EventArgs e)
        {
            queue_textbox.Text = "";
        }

        // Lorsque l'on demande de rajouter une ligne à la queue
        private void add_button_Click(object sender, EventArgs e)
        {
            // On utilise la fonction get_controls() et on met à jour la sortie
            queue_textbox.Text += get_controls() + Environment.NewLine;
            t.Sortie_Bottom(queue_textbox);
        }

        // Lorsque l'on demande de sauvegarder la queue
        private void save_button_Click(object sender, EventArgs e)
        {
            File.WriteAllText(saved, queue_textbox.Text);

            // Si le fichier a bien été créé on active le button de load
            if (File.Exists(saved)) load_button.Enabled = true;

            Process.Start("notepad.exe", saved);
        }

        // Lorsque l'on appuie sur le bouton load
        private void load_button_Click(object sender, EventArgs e)
        {
            try
            {
                // On copie le contenu du fichier dans la textbox de queue
                queue_textbox.Text = File.ReadAllText(saved);
            }
            catch
            {
                // On affiche un message d'erreur et on quitte l'application
                MessageBox.Show("Une erreur est survenue", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(-1);
            }
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("http://www.microsoft.com/download/en/details.aspx?id=35");
        }
    }
}
